﻿using Google.Protobuf.WellKnownTypes;
using MT5Collect;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using static System.Net.Mime.MediaTypeNames;
using static System.Windows.Forms.VisualStyles.VisualStyleElement;
using static System.Windows.Forms.VisualStyles.VisualStyleElement.ProgressBar;

namespace MT5DataCollect
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
            ConfigTool.GetConfig();
        }

        public delegate void ShowMsgDelegate(string msg);
        public void ShowMsg(string msg)
        {
            if (InvokeRequired)
            {
                this.Invoke(new ShowMsgDelegate(ShowMsg), msg);
            }
            else
            {
                rtb_Log.AppendText($"{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss:fff")}---{msg}\r\n");
                if (this.rtb_Log.Lines.Length > 1000)
                {
                    rtb_Log.Text = rtb_Log.Text.Remove(0, 500);
                }
                rtb_Log.ScrollToCaret();
            }
        }
        DataTable dt_Mt5Server;
        MT5Service mT5Service;
        ReportServer reportServer;
        string type = "";
        private void Form1_Shown(object sender, EventArgs e)
        {
            try
            {
                LoadSetting();
                if (type == "Report")
                {
                    Commission();
                    System.Windows.Forms.Application.Exit();
                }
                else
                {
                    GetMT5Server();
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show($"系统初始化失败，错误信息：{ex.Message}");
            }
        }

        #region 按钮

        /// <summary>
        /// 保存数据库设置
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btn_SaveDBSetting_Click(object sender, EventArgs e)
        {
            try
            {
                Dictionary<string, string> dbsetting = new Dictionary<string, string>();
                dbsetting.Add("IP", tb_IP.Text);
                dbsetting.Add("Port", tb_Port.Text);
                dbsetting.Add("UserID", tb_UserID.Text);
                dbsetting.Add("Password", tb_Password.Text);
                ConfigTool.SaveConfig(dbsetting);
                GetMT5Server();
                MessageBox.Show("保存成功");
            }
            catch (Exception ex)
            {
                MessageBox.Show($"保存失败，错误信息：{ex.Message}");
            }
        }

        /// <summary>
        /// 测试连接
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btn_ConnDB_Click(object sender, EventArgs e)
        {
            try
            {
                string connectionString = $"data source={tb_IP.Text};database=mt;user id={tb_UserID.Text};password={tb_Password.Text};pooling=true;port={tb_Port.Text};sslmode=none;charset=utf8;convert zero datetime=True";
                bool isSuccess = DBHelper.Connect(connectionString);
                if (isSuccess)
                {
                    MessageBox.Show("连接成功");
                }
                else
                {
                    MessageBox.Show("连接失败");
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show($"连接失败，错误信息：{ex.Message}");
            }
        }

        private void btn_All_Click(object sender, EventArgs e)
        {
            Thread thread = new Thread(() =>
            {

                GetMT5ServerList(Type.All.ToString());
            });
            thread.IsBackground = true;
            thread.Start();
        }

        private void btn_User_Click(object sender, EventArgs e)
        {
            Thread thread = new Thread(() =>
            {
                GetMT5ServerList(Type.User.ToString());
            });
            thread.IsBackground = true;
            thread.Start();
        }

        private void btn_Trade_Click(object sender, EventArgs e)
        {
            Thread thread = new Thread(() =>
            {
                GetMT5ServerList(Type.Trade.ToString());
            });
            thread.IsBackground = true;
            thread.Start();
        }

        private void btn_ToadyTrade_Click(object sender, EventArgs e)
        {
            Thread thread = new Thread(() =>
            {
                GetMT5ServerList(Type.TodayTrade.ToString());
            });
            thread.IsBackground = true;
            thread.Start();
        }

        #endregion

        /// <summary>
        /// 读取设置
        /// </summary>
        public void LoadSetting()
        {
            try
            {
                Dictionary<string, string> config = ConfigTool.GetConfig();
                tb_IP.Text = config["IP"] == null ? "" : config["IP"];
                tb_Port.Text = config["Port"] == null ? "" : config["Port"];
                tb_UserID.Text = config["UserID"] == null ? "" : config["UserID"];
                tb_Password.Text = config["Password"] == null ? "" : config["Password"];
                type = config["Type"] == null ? "" : config["Type"];
                DBHelper.connectionString = $"data source={tb_IP.Text};database=mt;user id={tb_UserID.Text};password={tb_Password.Text};pooling=true;port={tb_Port.Text};sslmode=none;charset=utf8;convert zero datetime=True";
                ShowMsg($"数据库设置初始化成功");
            }
            catch (Exception ex)
            {

                ShowMsg($"数据库设置初始化失败，异常：{ex.Message}");
            }
        }

        /// <summary>
        /// 读取MT5服务器列表
        /// </summary>
        public void GetMT5Server()
        {
            try
            {
                dt_Mt5Server = DBService.GetMt5Server();
                ShowMsg($"读取MT5服务器设置成功");
                Thread thread = new Thread(() =>
                {
                    GetMT5ServerList(type);
                });
                thread.IsBackground = true;
                thread.Start();
            }
            catch (Exception ex)
            {
                ShowMsg($"读取MT5服务器设置失败，异常：{ex.Message}");
            }
        }

        /// <summary>
        /// 遍历MT5服务器列表
        /// </summary>
        public void GetMT5ServerList(string type)
        {
            try
            {
                List<DataRow> dataRows = dt_Mt5Server.Select($"state=1 and type=1").ToList();
                ShowMsg($"获取到需要同步的MT5服务器数据{dataRows.Count}个");
                mT5Service = new MT5Service();
                mT5Service.INI(new ShowMsgDelegate(ShowMsg));
                if (dataRows.Count > 0)
                {
                    DBService.ClearPosition();
                    DBService.ClearOrder();
                    foreach (DataRow row in dataRows)
                    {
                        string metatrader_name = row["metatrader_name"].ToString();
                        string metatrader_server = row["metatrader_server"].ToString();
                        int metatrader_port = int.Parse(row["metatrader_port"].ToString());
                        ulong metatrader_login = ulong.Parse(row["metatrader_login"].ToString());
                        string metatrader_password = row["metatrader_password"].ToString();
                        OneMT5Server(metatrader_server, metatrader_port, metatrader_login, metatrader_password, type);
                    }
                }
            }
            catch (Exception ex)
            {
                ShowMsg($"{ex.Message}");
            }
        }

        /// <summary>
        /// 连接MT5服务器
        /// </summary>
        /// <param name="server"></param>
        /// <param name="port"></param>
        /// <param name="login"></param>
        /// <param name="password"></param>
        public void OneMT5Server(string server, int port, ulong login, string password, string type)
        {
            try
            {
                mT5Service.Connect(server, port, login, password);
                if (type == "Symbol")
                {
                    mT5Service.GetSymbol(server);
                }
                else
                {
                    mT5Service.GetUsers(server, type);
                }
            }
            catch (Exception)
            {
                throw;
            }
            finally
            {
                Disconnect();
            }
        }

        /// <summary>
        /// 断开MT5连接
        /// </summary>
        public void Disconnect()
        {
            int maxWorkerThreads, workerThreads;
            int portThreads;
            while (true)
            {
                /*
                 GetAvailableThreads()：检索由 GetMaxThreads 返回的线程池线程的最大数目和当前活动数目之间的差值。
                 而GetMaxThreads 检索可以同时处于活动状态的线程池请求的数目。
                 通过最大数目减可用数目就可以得到当前活动线程的数目，如果为零，那就说明没有活动线程，说明所有线程运行完毕。
                 */
                ThreadPool.GetMaxThreads(out maxWorkerThreads, out portThreads);
                ThreadPool.GetAvailableThreads(out workerThreads, out portThreads);
                if (maxWorkerThreads - workerThreads == 0)
                {
                    mT5Service.Disconnect();
                    System.Windows.Forms.Application.Exit();
                    break;
                }
            }
        }

        public enum Type
        {
            All,
            User,
            Trade,
            TodayTrade
        }

        #region 返佣统计计算

        private void Commission()
        {
            try
            {
                reportServer = new ReportServer();
                reportServer.INI(new ShowMsgDelegate(ShowMsg));
                //reportServer.Report(DateTime.Today.AddDays(-150), DateTime.Today);
                reportServer.Report();
                reportServer.CommissionToWallet();
            }
            catch (Exception ex)
            {
                ShowMsg($"{ex.Message}");
            }
        }

        private void btn_Commission_Click(object sender, EventArgs e)
        {
            try
            {
                Commission();
            }
            catch (Exception ex)
            {
                ShowMsg($"{ex.Message}");
            }
        }

        #endregion

    }
}
